﻿using Loki.UI;
using Loki.Utils;

namespace Loki.Engine
{
    /// <summary>
    /// Spring application engine (Loki default engine).
    /// </summary>
    public class SpringEngine : LokiObject, IApplicationEngine
    {
        /// <summary>
        /// Application model default name.
        /// </summary>
        public const string APPLICATIONMODEL_DEFAULTNAME = "ApplicationModel";

        /// <summary>
        /// Data model default name.
        /// </summary>
        public const string DATAMODEL_DEFAULTNAME = "DataContext";

        private static SpringContext _ApplicationContext;

        private static SpringContext _UIContext;

        private static SpringContext _DataContext;

        private const string CONTEXT_APPLICATION_NAME = "Model";

        private const string CONTEXT_APPLICATION_PATH = "assembly://Loki.Core/Loki.Config/model.xml";

        private const string CONTEXT_DATA_NAME = "Data";

        private const string CONTEXT_DATA_PATH = "assembly://Loki.Core/Loki.Config/data.xml";

        private const string CONTEXT_UI_PATH = "assembly://Loki.Core/Loki.Config/viewmodel.xml";

        private const string CONTEXT_UI_NAME = "UI";

        /// <summary>
        /// Initializes a new instance of the <see cref="SpringEngine"/> class.
        /// </summary>
        public SpringEngine()
        {
            _ApplicationContext = new SpringContext(CONTEXT_APPLICATION_NAME, CONTEXT_APPLICATION_PATH);
            _DataContext = new SpringContext(CONTEXT_DATA_NAME, CONTEXT_DATA_PATH);
            _UIContext = new SpringContext(CONTEXT_UI_NAME, CONTEXT_UI_PATH);
        }

        /// <summary>
        /// Loads the UI definitions.
        /// </summary>
        /// <param name="P_UIDefinitions">The UI definitions.</param>
        public void LoadUI(params string[] P_UIDefinitions)
        {
            _UIContext.LoadContext(P_UIDefinitions);
            _UIContext.EndLoad();
        }

        /// <summary>
        /// Loads the model definitions.
        /// </summary>
        /// <param name="P_ModelDefinitions">The model definitions.</param>
        public void LoadModel(params string[] P_ModelDefinitions)
        {
            _ApplicationContext.LoadContext(P_ModelDefinitions);
            _ApplicationContext.EndLoad();
        }

        /// <summary>
        /// Loads the data definitions.
        /// </summary>
        /// <param name="P_DataDefinitions">The data definitions.</param>
        public void LoadData(params string[] P_DataDefinitions)
        {
            _DataContext.LoadContext(P_DataDefinitions);
            _DataContext.EndLoad();
        }

        /// <summary>
        /// Gets the application model.
        /// </summary>
        /// <typeparam name="TApplicationModel">The type of the application model.</typeparam>
        /// <param name="P_ModelID">The model ID.</param>
        public TApplicationModel GetApplicationModel<TApplicationModel>(string P_ModelID)
        {
            return _ApplicationContext.GetObject<TApplicationModel>(P_ModelID);
        }

        /// <summary>
        /// Gets the application model.
        /// </summary>
        /// <typeparam name="TApplicationModel">The type of the application model.</typeparam>
        public TApplicationModel GetApplicationModel<TApplicationModel>()
        {
            return _ApplicationContext.GetObject<TApplicationModel>(APPLICATIONMODEL_DEFAULTNAME);
        }

        /// <summary>
        /// Gets the data model.
        /// </summary>
        /// <typeparam name="TDataModel">The type of the data model.</typeparam>
        public TDataModel GetDataModel<TDataModel>()
        {
            return _DataContext.GetObject<TDataModel>(DATAMODEL_DEFAULTNAME);
        }

        /// <summary>
        /// Gets the data model.
        /// </summary>
        /// <typeparam name="TDataModel">The type of the data model.</typeparam>
        /// <param name="P_ModelID">The model ID.</param>
        public TDataModel GetDataModel<TDataModel>(string P_ModelID)
        {
            return _DataContext.GetObject<TDataModel>(DATAMODEL_DEFAULTNAME);
        }

        /// <summary>
        /// Gets the specified viewmodel.
        /// </summary>
        /// <typeparam name="TViewModel">The type of the view model type.</typeparam>
        public TViewModel GetViewModel<TViewModel>() where TViewModel : IViewModel
        {
            return _UIContext.GetObject<TViewModel>(typeof(TViewModel).Name);
        }

        /// <summary>
        /// Gets the specified viewmodel.
        /// </summary>
        /// <typeparam name="TViewModel">The type of the view model.</typeparam>
        /// <param name="P_ModelID">The model ID.</param>
        public TViewModel GetViewModel<TViewModel>(string P_ModelID) where TViewModel : IViewModel
        {
            return _UIContext.GetObject<TViewModel>(P_ModelID);
        }
    }
}
